/*!
 * \file vrouter_core.c
 *
 * \brief 共通定义
 *
 * All Rights Reserved Copyright (C) 2014 broada,Co.,Ltd.\n
 * 共通使用的宏和结构体
 *
 * \version 1.0
 * \author jikw
 * \date 2017/6/26
 *
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "config.h"
#include "frct_comm.h"
#include "frreport_comm.h"
#include "frservice_comm.h"
#include "frbyte_buffer.h"
#include "iconv2utf8.h"
#include "vrouter_core.h"

extern void *g_p_apm_context;

typedef struct __st_L7session_vrouter_private
{
    unsigned long ul_seq;                       //序列号，1次req和response时，使用同一个序列号
    L4_transaction st_l4_trans;                 //数据
    Frreport_body_data *p_st_body_data_req;
    Frreport_body_data *p_st_body_data_resp;
    Frlist_header *p_lst_comm;
    Frlist_header *p_lst_req;
    Frbyte_Packet *p_req_packet;                //存请求bytebuff数据
    Frbyte_Packet *p_resp_packet;               //存相应bytebuff数据
} L7session_vrouter_private;

/*!
 * vrouter私有数据创建
 *
 * \param void
 *
 * \return NULL          内存分配失败\n
 *         p_st_private  内存分配成功
 *
 * \note
 *
 */
FR_STATIC L7session_vrouter_private* __vrouter_private_create(void)
{
    L7session_vrouter_private *p_st_private = NULL;
    p_st_private = (L7session_vrouter_private*)frmalloc(sizeof(L7session_vrouter_private));
    if (p_st_private == NULL)
        return NULL;
    memset(p_st_private, 0x00, sizeof(L7session_vrouter_private));

    return p_st_private;
}

/*!
 * 私有信息重置
 *
 * \param p_private_session  (vrouter的私有session数据)
 *
 * \return FR_SUCC   成功\n
 *
 * \note
 *
 */
FR_STATIC int __vrouter_session_reset(void *p_private_session)
{
    L7session_vrouter_private *p_st_private = (L7session_vrouter_private*)p_private_session;

    if (p_st_private)
    {
        if (p_st_private->p_st_body_data_req)
            frreport_body_free(&p_st_private->p_st_body_data_req);

        if (p_st_private->p_st_body_data_resp)
            frreport_body_free(&p_st_private->p_st_body_data_resp);

        if (p_st_private->p_lst_req)
            frreport_body_l7list_free(&p_st_private->p_lst_req);

        if (p_st_private->p_lst_comm)
            frreport_body_l7list_free(&p_st_private->p_lst_comm);

        if (p_st_private->p_req_packet)
            bytebuff_free(&(p_st_private->p_req_packet));

        if (p_st_private->p_resp_packet)
            bytebuff_free(&(p_st_private->p_resp_packet));
    }
    return FR_SUCC;
}

/*!
 * 判断是否是vrouter协议
 *
 * \param p_st_conn      (输入数据信息)
 * \param p_st_packet    (输入数据)
 *
 * \return APM_L7_IS_YES  属于vrouter协议\n
 *         APM_L7_IS_NO   不属于vrouter协议
 *
 * \note
 *
 */
int vrouter_detect(Conntrack *p_st_conn, Apm_packet *p_st_packet)
{
    int i_ret = 0;
    int *p_len;
    char arr_len[8];

    if (p_st_packet == NULL || p_st_packet->p_payload == NULL || p_st_packet->ui_payload_len < 27 || p_st_conn==NULL)
        return APM_L7_IS_NO;

	memset(arr_len, 0x00, sizeof(arr_len));

    /*
	#系统头
	总长度 (4bytes, 16进制网络序)：包括长度在内的整个报文的长度
	协议版本号(2bytes，字节)：要求第一个字节必须为1，第二个字节为0
	报文类型(1bytes, 字节)：0应用请求，2成功应答，3系统失败应答，4应用失败应答，其他保留。
	系统标识(4bytes，字符串)：0001交易路由，0002VMenu，0020小额支付。
	请求服务名称(10bytes, 字符串)：不足10位后补空格。
	应用报文类型(2bytes，字符串)：01Vrouter标准报文。
	应用报文长度(4bytes, 16进制网络序)
    */

	//总长度
    memcpy(arr_len, p_st_packet->p_payload, 4);
    p_len = (int *)arr_len;
    if (ntohl(*p_len) != p_st_packet->ui_payload_len)
        goto ERROR;
    //协议版本号
    if (memcmp(p_st_packet->p_payload+4, "\x01\x00", 2) != 0)
        goto ERROR;
    //系统标识
    if (memcmp(p_st_packet->p_payload+7, "\x30\x30\x30\x31", 4) != 0 &&
    	memcmp(p_st_packet->p_payload+7, "\x30\x30\x30\x32", 4) != 0 &&
    	memcmp(p_st_packet->p_payload+7, "\x30\x30\x32\x30", 4) != 0)
        goto ERROR;
    //应用报文类型
    if (memcmp(p_st_packet->p_payload+21, "\x30\x31", 2) != 0)
        goto ERROR;

    i_ret = frct_get_direct_known(p_st_conn);
    if (i_ret == FR_DIRECT_UNKNOWN)
    {
        //根据报文类型判断方向
        if (*(p_st_packet->p_payload+6) == '\x00')
        {
            frcap_set_cs_srv(p_st_conn, p_st_packet->dst_ip, p_st_packet->dst_port);
            frservice_add(g_p_apm_context, MODULE_L7PROTO, p_st_packet->dst_ip, p_st_packet->dst_port, NULL, 0);
        }
        else if (*(p_st_packet->p_payload+6) == '\x02' ||
            *(p_st_packet->p_payload+6) == '\x03' ||
            *(p_st_packet->p_payload+6) == '\x04')
        {
            frcap_set_cs_srv(p_st_conn, p_st_packet->src_ip, p_st_packet->src_port);
            frservice_add(g_p_apm_context, MODULE_L7PROTO, p_st_packet->src_ip, p_st_packet->src_port, NULL, 0);
        }
        else
            goto ERROR;
    }

    return APM_L7_IS_YES;

ERROR:
    if (frct_get_direct_known(p_st_conn) == FR_DIRECT_UNKNOWN)
    {
        i_ret = frservice_get(g_p_apm_context, MODULE_L7PROTO, p_st_packet->dst_ip, p_st_packet->dst_port, NULL, 0, NULL);
        if (i_ret == FR_SUCC)
        {
            frcap_set_cs_srv(p_st_conn, p_st_packet->dst_ip, p_st_packet->dst_port);
            return APM_L7_IS_YES;
        }
        i_ret = frservice_get(g_p_apm_context, MODULE_L7PROTO, p_st_packet->src_ip, p_st_packet->src_port, NULL, 0, NULL);
        if (i_ret == FR_SUCC)
        {
            frcap_set_cs_srv(p_st_conn, p_st_packet->src_ip, p_st_packet->src_port);
            return APM_L7_IS_YES;
        }
    }
    else
    {
        i_ret = frservice_get(g_p_apm_context, MODULE_L7PROTO, p_st_packet->src_ip, p_st_packet->src_port, NULL, 0, NULL);
        if (i_ret == FR_SUCC)
            return APM_L7_IS_YES;

        i_ret = frservice_get(g_p_apm_context, MODULE_L7PROTO, p_st_packet->dst_ip, p_st_packet->dst_port, NULL, 0, NULL);
        if (i_ret == FR_SUCC)
            return APM_L7_IS_YES;
    }
    return APM_L7_IS_NO;
}

/*!
 * req数据解析
 *
 * \param p_packet        (req数据)
 * \param p_st_body_data
 *
 * \return APM_L7_ANALYZE_SUCC   成功\n
 *         APM_L7_ANALYZE_FAIL   失败
 *
 * \note
 *
 */
FR_STATIC int __get_field(Frbyte_Packet *p_packet
                        , Frreport_body_data *p_st_body_data
                        , char *p_input)
{
	int i_count = 0;
    int i_limit = 0;
    uint8_t u8_type = 0;
    uint8_t u8_value = 0;
    uint32_t u32_count = 0;
    uint32_t u32_len = 0;
    uint32_t u32_name_len = 0;
    uint32_t u32_struct_len = 0;
    char arr_name[128];
    char arr_temp[128];
    char arr_value[12];
    char *p_name = NULL;
    char *p_value = NULL;

    if (p_packet == NULL || p_st_body_data == NULL)
        return FR_FAIL;

	memset(arr_name, 0x00, sizeof(arr_name));
	memset(arr_temp, 0x00, sizeof(arr_temp));
	memset(arr_value, 0x00, sizeof(arr_value));

	//字段名长度
    if (bytebuff_get_int(p_packet, 1, &u32_name_len, BYTE_BIG_ENDIAN) == FR_FAIL)
        goto ERROR;
    //字段名
    p_name = (char *)frmalloc(u32_name_len+1);
    if (p_name == NULL)
        goto ERROR;
    memset(p_name, 0x00, u32_name_len+1);
    if (bytebuff_get_bytes(p_packet, p_name, u32_name_len) == FR_FAIL)
        goto ERROR;
    snprintf(arr_name, sizeof(arr_name), "%s.%s", p_input, p_name);
    frfree(p_name);
    p_name = NULL;
	//字段类型
    if (bytebuff_get_char(p_packet, &u8_type) == FR_FAIL)
        goto ERROR;
    switch(u8_type)
    {
    	//结构开始
        case 0x01:
		    if (bytebuff_get_int(p_packet, 2, &u32_struct_len, BYTE_BIG_ENDIAN) == FR_FAIL)
		        goto ERROR;
			i_limit = bytebuff_getPosition(p_packet)+u32_struct_len;
			if (i_limit > (int)p_packet->ui_all_len)
				goto ERROR;
			while(bytebuff_getPosition(p_packet) < i_limit)
			{
				if (__get_field(p_packet, p_st_body_data, arr_name)==FR_FAIL )
					goto ERROR;
			}
        	break;
        //数组开始
        case 0x02:
		    if (bytebuff_get_int(p_packet, 2, &u32_count, BYTE_BIG_ENDIAN) == FR_FAIL)
		        goto ERROR;
		    if (bytebuff_get_int(p_packet, 2, &u32_len, BYTE_BIG_ENDIAN) == FR_FAIL)
		        goto ERROR;
			for(i_count=0; i_count < (int)u32_count; i_count++)
			{
				snprintf(arr_temp, sizeof(arr_temp), "%s.%d", arr_name, i_count+1);
				if (__get_field(p_packet, p_st_body_data, arr_name)==FR_FAIL )
					goto ERROR;
			}
        	break;
        //字节类型
        case 0x03:
		    if (bytebuff_get_char(p_packet, &u8_value) == FR_FAIL)
		        goto ERROR;
		    if (frreport_body_l7_add_int(p_st_body_data, arr_name, u8_value) == FR_FAIL)
		        goto ERROR;
        	break;
        //短整形数据
        case 0x04:
		    if (bytebuff_get_int(p_packet, 1, &u32_len, BYTE_BIG_ENDIAN) == FR_FAIL)
		        goto ERROR;
		    if (frreport_body_l7_add_int(p_st_body_data, arr_name, u32_len) == FR_FAIL)
		        goto ERROR;
        	break;
        //4位整形
        case 0x05:
		    if (bytebuff_get_int(p_packet, 4, &u32_len, BYTE_BIG_ENDIAN) == FR_FAIL)
		        goto ERROR;
		    if (frreport_body_l7_add_int(p_st_body_data, arr_name, u32_len) == FR_FAIL)
		        goto ERROR;
        	break;
        //小数
        case 0x06:
        //短字符串
        case 0x07:
		    if (bytebuff_get_int(p_packet, 1, &u32_len, BYTE_BIG_ENDIAN) == FR_FAIL)
		        goto ERROR;
		    p_value = (char *)frmalloc(u32_len+1);
		    if (p_value == NULL)
		        goto ERROR;
		    memset(p_value, 0x00, u32_len+1);
		    if (bytebuff_get_bytes(p_packet, p_value, u32_len) == FR_FAIL)
		        goto ERROR;
		    if (frreport_body_l7_add_str(p_st_body_data, arr_name, p_value) == FR_FAIL)
		        goto ERROR;
		    frfree(p_value);
		    p_value = NULL;
        	break;
        //短字节流
        case 0x08:
		    if (bytebuff_get_int(p_packet, 1, &u32_len, BYTE_BIG_ENDIAN) == FR_FAIL)
		        goto ERROR;
		    p_value = (char *)frmalloc(u32_len+1);
		    if (p_value == NULL)
		        goto ERROR;
		    memset(p_value, 0x00, u32_len+1);
		    if (bytebuff_get_bytes(p_packet, p_value, u32_len) == FR_FAIL)
		        goto ERROR;
		    if (frreport_body_l7_add_bin(p_st_body_data, arr_name, p_value, u32_len) == FR_FAIL)
		        goto ERROR;
		    frfree(p_value);
		    p_value = NULL;
        	break;
        //日期
        case 0x09:
		    if (bytebuff_get_bytes(p_packet, arr_value, 8) == FR_FAIL)
		        goto ERROR;
		    if (frreport_body_l7_add_str(p_st_body_data, arr_name, arr_value) == FR_FAIL)
		        goto ERROR;
        	break;
        //时间
        case 0x0a:
		    if (bytebuff_get_bytes(p_packet, arr_value, 6) == FR_FAIL)
		        goto ERROR;
		    if (frreport_body_l7_add_str(p_st_body_data, arr_name, arr_value) == FR_FAIL)
		        goto ERROR;
        	break;
        //长字符串
        case 0x0b:
		    if (bytebuff_peek_char(p_packet, &u8_value) == FR_FAIL)
		        goto ERROR;
        	if ((u8_value & 0x80) != 0)
        	{
			    if (bytebuff_get_int(p_packet, 4, &u32_len, BYTE_BIG_ENDIAN) == FR_FAIL)
			        goto ERROR;
        	}
        	else
        	{
			    if (bytebuff_get_int(p_packet, 2, &u32_len, BYTE_BIG_ENDIAN) == FR_FAIL)
			        goto ERROR;
        	}
		    p_value = (char *)frmalloc(u32_len+1);
		    if (p_value == NULL)
		        goto ERROR;
		    memset(p_value, 0x00, u32_len+1);
		    if (bytebuff_get_bytes(p_packet, p_value, u32_len) == FR_FAIL)
		        goto ERROR;
		    if (frreport_body_l7_add_str(p_st_body_data, arr_name, p_value) == FR_FAIL)
		        goto ERROR;
		    frfree(p_value);
		    p_value = NULL;
        	break;
        //长字节流
        case 0x0c:
		    if (bytebuff_peek_char(p_packet, &u8_value) == FR_FAIL)
		        goto ERROR;
        	if ((u8_value & 0x80) != 0)
        	{
			    if (bytebuff_get_int(p_packet, 4, &u32_len, BYTE_BIG_ENDIAN) == FR_FAIL)
			        goto ERROR;
        	}
        	else
        	{
			    if (bytebuff_get_int(p_packet, 2, &u32_len, BYTE_BIG_ENDIAN) == FR_FAIL)
			        goto ERROR;
        	}
		    p_value = (char *)frmalloc(u32_len+1);
		    if (p_value == NULL)
		        goto ERROR;
		    memset(p_value, 0x00, u32_len+1);
		    if (bytebuff_get_bytes(p_packet, p_value, u32_len) == FR_FAIL)
		        goto ERROR;
		    if (frreport_body_l7_add_bin(p_st_body_data, arr_name, p_value, u32_len) == FR_FAIL)
		        goto ERROR;
		    frfree(p_value);
		    p_value = NULL;
            break;
        //加密字段
        case 0x0d:
		    if (bytebuff_get_int(p_packet, 1, &u32_len, BYTE_BIG_ENDIAN) == FR_FAIL)
		        goto ERROR;
            if (bytebuff_skip(p_packet, u32_len) != FR_SUCC)
                goto ERROR;
		    if (bytebuff_peek_char(p_packet, &u8_value) == FR_FAIL)
		        goto ERROR;
        	if ((u8_value & 0x80) != 0)
        	{
			    if (bytebuff_get_int(p_packet, 4, &u32_len, BYTE_BIG_ENDIAN) == FR_FAIL)
			        goto ERROR;
        	}
        	else
        	{
			    if (bytebuff_get_int(p_packet, 2, &u32_len, BYTE_BIG_ENDIAN) == FR_FAIL)
			        goto ERROR;
        	}
		    p_value = (char *)frmalloc(u32_len+1);
		    if (p_value == NULL)
		        goto ERROR;
		    memset(p_value, 0x00, u32_len+1);
		    if (bytebuff_get_bytes(p_packet, p_value, u32_len) == FR_FAIL)
		        goto ERROR;
		    if (frreport_body_l7_add_bin(p_st_body_data, arr_name, p_value, u32_len) == FR_FAIL)
		        goto ERROR;
		    frfree(p_value);
		    p_value = NULL;
            break;
        default:
            goto ERROR;
    }

	return FR_SUCC;

ERROR:
    if (p_name)
    {
    	frfree(p_name);
    	p_name = NULL;
    }
    if (p_value)
	{
		frfree(p_value);
		p_value = NULL;
	}

    return FR_FAIL;
}

/*!
 * req数据解析
 *
 * \param p_packet        (req数据)
 * \param p_st_body_data
 *
 * \return APM_L7_ANALYZE_SUCC   成功\n
 *         APM_L7_ANALYZE_FAIL   失败
 *
 * \note
 *
 */
FR_STATIC int __req_parse(Frbyte_Packet *p_packet
                        , Frreport_body_data *p_st_body_data)
{
	int i_limit = 0;
    uint8_t u8_type = 0;
    uint32_t u32_len = 0;
    uint32_t u32_body_len = 0;
    uint32_t u32_head_len = 0;
    uint32_t u32_mac_len = 0;
    char arr_temp[12];
    char arr_features[12];
    char *p_mac = NULL;

    if (p_packet == NULL || p_st_body_data == NULL)
        return APM_L7_ANALYZE_FAIL;

	//解析系统头
	//总长度
    if (bytebuff_get_int(p_packet, 4, &u32_len, BYTE_BIG_ENDIAN) == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;
    if (u32_len != p_packet->ui_all_len)
        return APM_L7_ANALYZE_FAIL;
	//协议版本号
    if (bytebuff_get_bytes(p_packet, arr_temp, 2) == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;
    arr_temp[2] = '\0';
    if (memcmp(arr_temp, "\x01\x00", 2) != 0)
        return APM_L7_ANALYZE_FAIL;
	//报文类型:应用请求
    if (bytebuff_get_char(p_packet, &u8_type) == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;
	//    if (u8_type != '\x00')
	//    	return APM_L7_ANALYZE_FAIL;
	//系统标识TODO
    if (bytebuff_get_bytes(p_packet, arr_temp, 4) == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;
    arr_temp[4] = '\0';
    if (memcmp(arr_temp, "\x30\x30\x30\x31", 4) != 0 &&
    	memcmp(arr_temp, "\x30\x30\x30\x32", 4) != 0 &&
    	memcmp(arr_temp, "\x30\x30\x32\x30", 4) != 0)
        return APM_L7_ANALYZE_FAIL;
    if (frreport_body_l7_add_str(p_st_body_data, "transaction.channel_code", arr_temp) == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;
    if (frreport_body_l7_add_str(p_st_body_data, "transaction.channel_name", arr_temp) == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;
	//请求服务名称
    if (bytebuff_get_bytes(p_packet, arr_temp, 10) == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;
    arr_temp[10] = '\0';
    frtrim(arr_temp);
    if (frreport_body_l7_add_str(p_st_body_data, APM_REPORT_KEY_TRANS_TITLE, arr_temp) == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;
    if (frreport_body_l7_add_str(p_st_body_data, "transaction.type_code", arr_temp) == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;
    if (frreport_body_l7_add_str(p_st_body_data, "transaction.type_name", arr_temp) == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;
	//应用报文类型
    if (bytebuff_get_bytes(p_packet, arr_temp, 2) == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;
    arr_temp[2] = '\0';
    if (memcmp(arr_temp, "\x30\x31", 2) != 0)
        return APM_L7_ANALYZE_FAIL;
	//应用报文长度
    if (bytebuff_get_int(p_packet, 4, &u32_body_len, BYTE_BIG_ENDIAN) == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;

	//解析可选系统头
	//可选头长度
    if (bytebuff_get_int(p_packet, 4, &u32_head_len, BYTE_BIG_ENDIAN) == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;
    //报文可选特性标识
    if (bytebuff_get_bytes(p_packet, arr_features, 4) == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;
    arr_features[4] = '\0';
	if ((*arr_features & 0x40) != 0)
	{
	    if (bytebuff_get_bytes(p_packet, arr_temp, 6) == FR_FAIL)
	        return APM_L7_ANALYZE_FAIL;
	    arr_temp[6] = '\0';
        if (frreport_body_l7_add_str(p_st_body_data, "request.vrouter.encrypt", arr_temp) == FR_FAIL)
            return APM_L7_ANALYZE_FAIL;
	}
	if ((*arr_features & 0x20) != 0)
	{
	    if (bytebuff_get_int(p_packet, 4, &u32_mac_len, BYTE_BIG_ENDIAN) == FR_FAIL)
	        goto ERROR;

	    if (bytebuff_get_bytes(p_packet, arr_temp, 6) == FR_FAIL)
	        goto ERROR;
	    arr_temp[6] = '\0';
        if (frreport_body_l7_add_str(p_st_body_data, "request.vrouter.mac.key", arr_temp) == FR_FAIL)
            goto ERROR;

        p_mac = (char *)frmalloc(u32_mac_len+1);
        if (p_mac == NULL)
            goto ERROR;
        memset(p_mac, 0x00, u32_mac_len+1);
        if (bytebuff_get_bytes(p_packet, p_mac, u32_mac_len) == FR_FAIL)
            goto ERROR;
        if (frreport_body_l7_add_bin(p_st_body_data, "request.vrouter.mac.value", p_mac, u32_mac_len) == FR_FAIL)
            goto ERROR;
        frfree(p_mac);
	}

	//解析报文主体
	i_limit = bytebuff_getPosition(p_packet)+u32_body_len;
	if (i_limit > (int)p_packet->ui_all_len)
		goto ERROR;
	while(bytebuff_getPosition(p_packet) < i_limit)
	{
		if (__get_field(p_packet, p_st_body_data, (char *)"request.vrouter")==FR_FAIL  )
			goto ERROR;
	}

    return APM_L7_ANALYZE_SET_REQ(APM_L7_ANALYZE_SUCC);

ERROR:
    if (p_mac)
        frfree(p_mac);

    return APM_L7_ANALYZE_FAIL;
}

/*!
 * resp数据解析
 *
 * \param p_packet        (resp数据)
 * \param p_st_body_data
 *
 * \return APM_L7_ANALYZE_SET_RESP(APM_L7_ANALYZE_SUCC)   成功\n
 *         APM_L7_ANALYZE_FAIL   失败
 *
 * \note
 *
 */
FR_STATIC int __resp_parse(Frbyte_Packet *p_packet
                         , Frreport_body_data *p_st_body_data)
{
	int i_limit = 0;
    uint8_t u8_type = 0;
    uint32_t u32_len = 0;
    uint32_t u32_body_len = 0;
    uint32_t u32_head_len = 0;
    uint32_t u32_mac_len = 0;
    char arr_temp[12];
    char arr_features[12];
    char *p_mac = NULL;

    if (p_packet == NULL || p_st_body_data == NULL)
        return APM_L7_ANALYZE_FAIL;

	//解析系统头
	//总长度
    if (bytebuff_get_int(p_packet, 4, &u32_len, BYTE_BIG_ENDIAN) == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;
    if (u32_len != p_packet->ui_all_len)
        return APM_L7_ANALYZE_FAIL;
	//协议版本号
    if (bytebuff_get_bytes(p_packet, arr_temp, 2) == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;
    arr_temp[2] = '\0';
    if (memcmp(arr_temp, "\x01\x00", 2) != 0)
        return APM_L7_ANALYZE_FAIL;
	//报文类型:应用请求
    if (bytebuff_get_char(p_packet, &u8_type) == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;
	//    if (u8_type != '\x00')
	//    	return APM_L7_ANALYZE_FAIL;
	//系统标识
    if (bytebuff_get_bytes(p_packet, arr_temp, 4) == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;
    arr_temp[4] = '\0';
    if (memcmp(arr_temp, "\x30\x30\x30\x31", 4) != 0 &&
    	memcmp(arr_temp, "\x30\x30\x30\x32", 4) != 0 &&
    	memcmp(arr_temp, "\x30\x30\x32\x30", 4) != 0)
        return APM_L7_ANALYZE_FAIL;
	//用应答错误编码TODO
    if (bytebuff_get_bytes(p_packet, arr_temp, 10) == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;
    arr_temp[10] = '\0';
    frtrim(arr_temp);
    if (frreport_body_l7_add_str(p_st_body_data, "response.error_message", arr_temp) == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;
	//应用报文类型
    if (bytebuff_get_bytes(p_packet, arr_temp, 2) == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;
    arr_temp[2] = '\0';
    if (memcmp(arr_temp, "\x30\x31", 2) != 0)
        return APM_L7_ANALYZE_FAIL;
	//应用报文长度
    if (bytebuff_get_int(p_packet, 4, &u32_body_len, BYTE_BIG_ENDIAN) == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;

	//解析可选系统头
	//可选头长度
    if (bytebuff_get_int(p_packet, 4, &u32_head_len, BYTE_BIG_ENDIAN) == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;
    //报文可选特性标识
    if (bytebuff_get_bytes(p_packet, arr_features, 4) == FR_FAIL)
        return APM_L7_ANALYZE_FAIL;
    arr_features[4] = '\0';
	if ((*arr_features & 0x40) != 0)
	{
	    if (bytebuff_get_bytes(p_packet, arr_temp, 6) == FR_FAIL)
	        return APM_L7_ANALYZE_FAIL;
	    arr_temp[6] = '\0';
        if (frreport_body_l7_add_str(p_st_body_data, "response.vrouter.encrypt", arr_temp) == FR_FAIL)
            return APM_L7_ANALYZE_FAIL;
	}
	if ((*arr_features & 0x20) != 0)
	{
	    if (bytebuff_get_int(p_packet, 4, &u32_mac_len, BYTE_BIG_ENDIAN) == FR_FAIL)
	        goto ERROR;

	    if (bytebuff_get_bytes(p_packet, arr_temp, 6) == FR_FAIL)
	        goto ERROR;
	    arr_temp[6] = '\0';
        if (frreport_body_l7_add_str(p_st_body_data, "response.vrouter.mac.key", arr_temp) == FR_FAIL)
            goto ERROR;

        p_mac = (char *)frmalloc(u32_mac_len+1);
        if (p_mac == NULL)
            goto ERROR;
        memset(p_mac, 0x00, u32_mac_len+1);
        if (bytebuff_get_bytes(p_packet, p_mac, u32_mac_len) == FR_FAIL)
            goto ERROR;
        if (frreport_body_l7_add_bin(p_st_body_data, "response.vrouter.mac.value", p_mac, u32_mac_len) == FR_FAIL)
            goto ERROR;
        frfree(p_mac);
	}

	//解析报文主体
	i_limit = bytebuff_getPosition(p_packet)+u32_body_len;
	if (i_limit > (int)p_packet->ui_all_len)
		goto ERROR;
	while(bytebuff_getPosition(p_packet) < i_limit)
	{
		if (__get_field(p_packet, p_st_body_data, (char *)"response.vrouter")==FR_FAIL )
			goto ERROR;
	}

    return APM_L7_ANALYZE_SET_RESP(APM_L7_ANALYZE_SUCC);

ERROR:
    if (p_mac)
        frfree(p_mac);

    return APM_L7_ANALYZE_FAIL;
}

/*!
 * vrouter的packet解析
 *
 * \param p_st_conn          (入力链接信息)
 * \param p_st_packet        (入力packet信息)
 * \param p_st_hash_report   (保存Frreport_data)
 * \param p_st_session       (私有数据)
 *
 * \return APM_L7_ANALYZE_SUCC   成功\n
 *         APM_L7_ANALYZE_FAIL   失败
 *         APM_L7_ANALYZE_TODO
 *
 * \note
 *
 */
FR_STATIC int __req_data_analysis(Conntrack *p_st_conn
                                , Apm_packet *p_st_packet
                                , Frhash_header *p_st_hash_report
                                , L7_session *p_st_session)
{
	uint32_t u32_len = 0;
    int i_ret = 0;
    unsigned long ul_tmp = 0;
    L4_transaction *p_st_l4_trans = NULL;
    Frreport_data *p_st_report_data = NULL;
    L7session_vrouter_private *p_st_private = NULL;

    if (p_st_conn == NULL || p_st_packet == NULL || p_st_hash_report == NULL || p_st_session == NULL)
        return APM_L7_ANALYZE_FAIL;

    p_st_private = (L7session_vrouter_private*)p_st_session->p_session_private;
    p_st_l4_trans = &(p_st_private->st_l4_trans);

    //如果连续的两个request
    if (p_st_private->p_lst_comm)
        __vrouter_session_reset((void *)(p_st_private));

    //创建数据链表
    if (p_st_private->p_st_body_data_req == NULL)
    {
        p_st_private->p_st_body_data_req = frreport_body_new_l7(p_st_conn);
        if (p_st_private->p_st_body_data_req == NULL)
            goto ERROR;

        if (frreport_body_l7_add_connInfo(p_st_private->p_st_body_data_req, p_st_conn) == FR_FAIL)
            goto ERROR;

        //seq ++
        p_st_private->ul_seq = frct_seq_increase(p_st_conn);

        if (p_st_l4_trans->st_request_time_first_byte.tv_sec==0 && p_st_l4_trans->st_request_time_first_byte.tv_usec==0)
        {
            //st_request_time_first_byte
            p_st_l4_trans->st_request_time_first_byte.tv_sec = p_st_packet->st_timestamp.tv_sec;
            p_st_l4_trans->st_request_time_first_byte.tv_usec = p_st_packet->st_timestamp.tv_usec;
        }

        //创建bytebuff
        if (p_st_private->p_req_packet == NULL)
        {
            p_st_private->p_req_packet = bytebuff_creat();
            if (p_st_private->p_req_packet == NULL)
                goto ERROR;
        }
    }
    //请求的字节数
    p_st_l4_trans->l_request_bytes += p_st_packet->ui_payload_len;

    if (p_st_private->p_req_packet == NULL)
        goto ERROR;

    //把这个包的数据先全加进bytebuff里
    if (bytebuff_add(p_st_private->p_req_packet, p_st_packet->p_payload, p_st_packet->ui_payload_len) != FR_SUCC)
        goto ERROR;

    if (bytebuff_get_int(p_st_private->p_req_packet, 4, &u32_len, BYTE_BIG_ENDIAN) == FR_FAIL)
        goto ERROR;
    if (u32_len > p_st_private->p_req_packet->ui_all_len)
    {
        bytebuff_rewind(p_st_private->p_req_packet);
        return APM_L7_ANALYZE_TODO;
    }
    bytebuff_rewind(p_st_private->p_req_packet);

    //req解析
    i_ret = __req_parse(p_st_private->p_req_packet, p_st_private->p_st_body_data_req);
    if (i_ret == APM_L7_ANALYZE_FAIL)
        goto ERROR;

    if (frreport_body_l7_add_ulong(p_st_private->p_st_body_data_req, APM_REPORT_KEY_REQ_ID, p_st_private->ul_seq) == FR_FAIL)
        goto ERROR;

    //start time
    if (frreport_body_l7_add_timeval(p_st_private->p_st_body_data_req, APM_REPORT_KEY_REQ_START_TIMESTAMP, &p_st_l4_trans->st_request_time_first_byte) == FR_FAIL)
        goto ERROR;

    //st_request_time
    p_st_l4_trans->st_request_time.tv_sec = p_st_packet->st_timestamp.tv_sec;
    p_st_l4_trans->st_request_time.tv_usec = p_st_packet->st_timestamp.tv_usec;

    ul_tmp = frtime_diff(&(p_st_l4_trans->st_request_time_first_byte), &(p_st_l4_trans->st_request_time));
    //send_time_us
    if (frreport_body_l7_add_long(p_st_private->p_st_body_data_req, APM_REPORT_KEY_REQ_SEND_TIME_US, ul_tmp) == FR_FAIL)
        goto ERROR;

    //request bytes
    if (frreport_body_l7_add_long(p_st_private->p_st_body_data_req, APM_REPORT_KEY_REQ_DATA_BYTES, p_st_l4_trans->l_request_bytes) == FR_FAIL)
        goto ERROR;

    //end time
    if (frreport_body_l7_add_timeval(p_st_private->p_st_body_data_req, APM_REPORT_KEY_REQ_END_TIMESTAMP, &p_st_l4_trans->st_request_time) == FR_FAIL)
        goto ERROR;

    p_st_report_data = frreport_data_l7_new(FRREPORT_TYPE_L7DATA_REQ);
    if (p_st_report_data == NULL)
        goto ERROR;

    //拷贝相关链表
    p_st_private->p_lst_comm = FRREPORT_BODY_L7LIST_CLONE_COMM(p_st_private->p_st_body_data_req);
    if (p_st_private->p_lst_comm == NULL)
        goto ERROR;
    p_st_private->p_lst_req = FRREPORT_BODY_L7LIST_CLONE_REQ(p_st_private->p_st_body_data_req);
    if (p_st_private->p_lst_req == NULL)
        goto ERROR;

    if (frreport_data_add_body(p_st_report_data, p_st_private->p_st_body_data_req) == FR_FAIL)
        goto ERROR;
    p_st_private->p_st_body_data_req = NULL;

    if (frreport_data_hash(p_st_hash_report, p_st_report_data) == FR_FAIL)
        goto ERROR;
    p_st_report_data = NULL;

    return i_ret;

ERROR:
    if (p_st_report_data)
        frreport_data_free(&p_st_report_data);
    __vrouter_session_reset((void *)(p_st_private));
    return APM_L7_ANALYZE_FAIL;
}

/*!
 * vrouter的packet解析
 *
 * \param p_st_conn          (入力链接信息)
 * \param p_st_packet        (入力packet信息)
 * \param p_st_hash_report   (保存Frreport_data)
 * \param p_st_session       (私有数据)
 *
 * \return APM_L7_ANALYZE_SUCC   成功\n
 *         APM_L7_ANALYZE_FAIL   失败
 *         APM_L7_ANALYZE_TODO
 *
 * \note
 *
 */
FR_STATIC int __resp_data_analysis(Conntrack *p_st_conn
                                 , Apm_packet *p_st_packet
                                 , Frhash_header *p_st_hash_report
                                 , L7_session *p_st_session)
{
	uint32_t u32_len = 0;
    int i_ret = 0;
    unsigned long ul_tmp = 0;
    L4_transaction *p_st_l4_trans = NULL;
    Frreport_data* p_st_report_data = NULL;
    L7session_vrouter_private *p_st_private = NULL;

    if (p_st_conn == NULL || p_st_packet == NULL || p_st_hash_report == NULL || p_st_session == NULL)
        return APM_L7_ANALYZE_FAIL;

    p_st_private = (L7session_vrouter_private*)p_st_session->p_session_private;
    p_st_l4_trans = &(p_st_private->st_l4_trans);

    if (p_st_private->p_st_body_data_resp == NULL)
    {
        //创建数据链表
        p_st_private->p_st_body_data_resp = frreport_body_new_l7(p_st_conn);
        if (p_st_private->p_st_body_data_resp == NULL)
            goto ERROR;

        if (p_st_l4_trans->st_response_time_first_byte.tv_sec == 0 && p_st_l4_trans->st_response_time_first_byte.tv_usec == 0)
        {
            p_st_l4_trans->st_response_time_first_byte.tv_sec = p_st_packet->st_timestamp.tv_sec;
            p_st_l4_trans->st_response_time_first_byte.tv_usec = p_st_packet->st_timestamp.tv_usec;
        }

        //创建bytebuff
        if (p_st_private->p_resp_packet == NULL)
        {
            p_st_private->p_resp_packet = bytebuff_creat();
            if (p_st_private->p_resp_packet == NULL)
                goto ERROR;
        }
    }

    //请求的字节数
    p_st_l4_trans->l_response_bytes += p_st_packet->ui_payload_len;

    if (p_st_private->p_resp_packet == NULL)
        goto ERROR;

    if (bytebuff_add(p_st_private->p_resp_packet, p_st_packet->p_payload, p_st_packet->ui_payload_len) != FR_SUCC)
        goto ERROR;

    if (bytebuff_get_int(p_st_private->p_resp_packet, 4, &u32_len, BYTE_BIG_ENDIAN) == FR_FAIL)
        goto ERROR;
    if (u32_len > p_st_private->p_resp_packet->ui_all_len)
    {
        bytebuff_rewind(p_st_private->p_resp_packet);
        return APM_L7_ANALYZE_TODO;
    }
    bytebuff_rewind(p_st_private->p_resp_packet);

    //resp解析
    i_ret = __resp_parse(p_st_private->p_resp_packet, p_st_private->p_st_body_data_resp);
    if (i_ret == APM_L7_ANALYZE_FAIL)
        goto ERROR;

    //数据上报
    if (p_st_l4_trans->st_request_time_first_byte.tv_sec != 0)
    {
        FRREPORT_BODY_L7LIST_SET_REQ(p_st_private->p_st_body_data_resp, &p_st_private->p_lst_req);
        FRREPORT_BODY_L7LIST_SET_COMM(p_st_private->p_st_body_data_resp, &p_st_private->p_lst_comm);
        p_st_private->p_lst_req = NULL;
        p_st_private->p_lst_comm = NULL;
    }
    else
    {
        if (frreport_body_l7_add_connInfo(p_st_private->p_st_body_data_resp, p_st_conn) == FR_FAIL)
           goto ERROR;
    }

    //start time
    if (frreport_body_l7_add_timeval(p_st_private->p_st_body_data_resp, APM_REPORT_KEY_RESP_START_TIMESTAMP, &p_st_l4_trans->st_response_time_first_byte) == FR_FAIL)
        goto ERROR;

    if (p_st_l4_trans->st_request_time.tv_sec != 0 || p_st_l4_trans->st_request_time.tv_usec != 0)
    {
        //server time
        ul_tmp = frtime_diff(&(p_st_l4_trans->st_request_time), &(p_st_l4_trans->st_response_time_first_byte));
        if (frreport_body_l7_add_ulong(p_st_private->p_st_body_data_resp, APM_REPORT_KEY_RESP_SERVER_TIME_US, ul_tmp) == FR_FAIL)
            goto ERROR;
    }
    else
    {
        if (frreport_body_l7_add_ulong(p_st_private->p_st_body_data_resp, APM_REPORT_KEY_RESP_SERVER_TIME_US, 0) == FR_FAIL)
            goto ERROR;
    }

    //st_response_time
    p_st_l4_trans->st_response_time.tv_sec = p_st_packet->st_timestamp.tv_sec;
    p_st_l4_trans->st_response_time.tv_usec = p_st_packet->st_timestamp.tv_usec;

    if (frreport_body_l7_add_long(p_st_private->p_st_body_data_resp, APM_REPORT_KEY_RESP_DATA_BYTES, p_st_l4_trans->l_response_bytes) == FR_FAIL)
        goto ERROR;

    //down load time
    ul_tmp = frtime_diff(&(p_st_l4_trans->st_response_time_first_byte), &(p_st_l4_trans->st_response_time));
    if (frreport_body_l7_add_long(p_st_private->p_st_body_data_resp, APM_REPORT_KEY_RESP_DOWNLOAD_TIME_US, ul_tmp) == FR_FAIL)
        goto ERROR;

    //end time
    if (frreport_body_l7_add_timeval(p_st_private->p_st_body_data_resp, APM_REPORT_KEY_RESP_END_TIMESTAMP, &p_st_l4_trans->st_response_time) == FR_FAIL)
        goto ERROR;

    p_st_report_data = frreport_data_l7_new(FRREPORT_TYPE_L7DATA_RESP);
    if (p_st_report_data == NULL)
        goto ERROR;

    if (frreport_data_add_body(p_st_report_data, p_st_private->p_st_body_data_resp) == FR_FAIL)
        goto ERROR;
    p_st_private->p_st_body_data_resp = NULL;

    if (frreport_data_hash(p_st_hash_report, p_st_report_data) == FR_FAIL)
        goto ERROR;
    p_st_report_data = NULL;

    vrouter_session_destroy(p_st_session->p_session_private);
    p_st_session->p_session_private = NULL;

    return i_ret;

ERROR:
    if (p_st_report_data)
        frreport_data_free(&p_st_report_data);
    vrouter_session_destroy((void *)(p_st_private));
    p_st_session->p_session_private = NULL;
    return APM_L7_ANALYZE_FAIL;
}

/*!
 * vrouter的packet解析
 *
 * \param p_st_conn          (入力链接信息)
 * \param p_st_packet        (入力packet信息)
 * \param p_st_hash_report   (保存Frreport_data)
 *
 * \return APM_L7_ANALYZE_SUCC   成功\n
 *         APM_L7_ANALYZE_FAIL   失败
 *
 * \note
 *
 */
int vrouter_analysis(Conntrack *p_st_conn
                           , Apm_packet *p_st_packet
                           , Frhash_header *p_st_hash_report)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    L7_session *p_st_session = NULL;

    if (p_st_conn == NULL || p_st_packet == NULL || p_st_hash_report == NULL)
        return APM_L7_ANALYZE_FAIL;

    //到Conntrack中取得session信息
    p_st_session = frct_get_session(p_st_conn);
    if (p_st_session == NULL)
        return APM_L7_ANALYZE_FAIL;

    //fin、syn包销毁私有数据
    if (p_st_packet->em_analyz_cmd == FRANALYZ_CMD_FIN || p_st_packet->em_analyz_cmd == FRANALYZ_CMD_SYN)
    {
        vrouter_session_destroy(p_st_session->p_session_private);
        p_st_session->p_session_private = NULL;
        return APM_L7_ANALYZE_SUCC;
    }

    //p_session_private分配内存
    if (p_st_session->p_session_private == NULL)
    {
        p_st_session->p_session_private = __vrouter_private_create();
        //内存分配失败
        if (p_st_session->p_session_private == NULL)
            return APM_L7_ANALYZE_FAIL;
    }

    //request
    if (p_st_packet->i_direction == FR_DIRECT_CLIENT2SRV)
    {
        i_ret = __req_data_analysis(p_st_conn, p_st_packet, p_st_hash_report, p_st_session);
        if (i_ret == APM_L7_ANALYZE_FAIL)
            goto ERROR;
        return i_ret;
    }
    //response
    else
    {
        i_ret = __resp_data_analysis(p_st_conn, p_st_packet, p_st_hash_report, p_st_session);
        if (i_ret == APM_L7_ANALYZE_FAIL)
            goto ERROR;
        return i_ret;
    }

ERROR:
    vrouter_session_destroy(p_st_session->p_session_private);
    p_st_session->p_session_private = NULL;
    return APM_L7_ANALYZE_FAIL;
}

/*!
 * 私有信息销毁
 *
 * \param p_private_session  (vrouter的私有session数据)
 *
 * \return FR_SUCC   成功\n
 *
 * \note
 *
 */
int vrouter_session_destroy(void *p_private_session)
{
    L7session_vrouter_private *p_st_private = (L7session_vrouter_private*)p_private_session;

    if (p_st_private)
    {
        if (p_st_private->p_st_body_data_req)
            frreport_body_free(&p_st_private->p_st_body_data_req);

        if (p_st_private->p_st_body_data_resp)
            frreport_body_free(&p_st_private->p_st_body_data_resp);

        if (p_st_private->p_lst_req)
            frreport_body_l7list_free(&p_st_private->p_lst_req);

        if (p_st_private->p_lst_comm)
            frreport_body_l7list_free(&p_st_private->p_lst_comm);

        if (p_st_private->p_req_packet)
            bytebuff_free(&(p_st_private->p_req_packet));

        if (p_st_private->p_resp_packet)
            bytebuff_free(&(p_st_private->p_resp_packet));

        frfree(p_st_private);
    }

    return FR_SUCC;
}
